﻿using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using DimensionsHelper.LanguageService.Protocol;

namespace DimensionsHelper.LanguageService.Syntax;

public class Macro : SourceNode, IDeclaration
{
    private readonly SourceNode _defineKeywordToken;
    private readonly SourceNode _nameIdentifier;


    private SourceNodeList? _definitions;
    private MacroParameterList? _parameterList;

    internal Macro(SourceNode? parent, SourceNode defineKeywordToken, SourceNode name) :
        base(parent, SyntaxKinds.MacroDeclaration)
    {
        SetChildField(ref _defineKeywordToken, defineKeywordToken);
        SetChildField(ref _nameIdentifier, name);
        _definitions = new SourceNodeList();
    }


    /// <summary>
    ///     宏名称
    /// </summary>
    public SourceNode NameIdentifier => _nameIdentifier;


    /// <summary>
    ///     是否声明为参数宏
    /// </summary>
    [MemberNotNullWhen(true, nameof(ParameterList))]
    public bool IsParametered => ParameterList != null;


    /// <summary>
    ///     宏参数列表
    /// </summary>
    public MacroParameterList? ParameterList => _parameterList;


    /// <summary>
    ///     宏定义列表
    /// </summary>
    public IReadOnlyList<SourceNode> Definitions =>
        _definitions != null ? _definitions : Array.Empty<SourceNode>();


    /// <summary>
    ///     宏定义列表中的Token数量
    /// </summary>
    public int DefinitionCount => _definitions?.Count ?? 0;


    public ITextNode DeclareKeywordToken => _defineKeywordToken;

    public string Name => NameIdentifier.Text;

    ITextNode IDeclaration.NameIdentifier => _nameIdentifier;


    public bool IsSignature => false;

    public bool IsTypeSignature => false;


    public bool ContainsModifier(SyntaxKinds modifierKind)
    {
        return false;
    }

    public bool ContainsAnyModifier(params SyntaxKinds[] modifiersKinds)
    {
        return false;
    }


    public override void AcceptVisitor<T>(SyntaxNodeVisitor<T> visitor)
    {
        Accept(visitor, NameIdentifier);
        AcceptList(visitor, Definitions);
    }


    internal override void SetUri(DocumentUri uri)
    {
        base.SetUri(uri);
        _parameterList?.SetUri(uri);

        if (_definitions != null)
        {
            _definitions.Uri = uri;
        }
    }


    /// <summary>
    ///     更新参数列表
    /// </summary>
    public Macro Update(MacroParameterList parameterList)
    {
        SetChildNullableField(ref _parameterList, parameterList);
        return this;
    }


    /// <summary>
    ///     向定义列表中添加一个新的Token节点。
    /// </summary>
    internal void AddDefinition(SourceNode definition)
    {
        _definitions ??= new SourceNodeList();
        _definitions.Add(definition);
    }
}


public static partial class NodeFactory
{
    public static Macro CreateMacro(SourceNode? parent, SourceNode defineKeywordToken, SourceNode nameIdentifier,
        MacroParameterList? parameterList)
    {
        Debug.Assert(defineKeywordToken.IsNode(SyntaxKinds.PreDefineKeywordToken));
        Debug.Assert(nameIdentifier.IsIdentifier && !SourceNode.IsNullOrDefault(nameIdentifier));
        Macro macro = new(parent, defineKeywordToken, nameIdentifier);
        if (parameterList != null)
        {
            macro.Update(parameterList);
        }

        return macro;
    }
}